package com.googlecode.mailnet.netmodel;

import java.util.*;
import java.io.Serializable;

/**
 * Network configuration.
 * <p/>
 * This class is <b>not thread-safe</b> for modifications.
 *
 * @author Iskander Akishev
 */
public class NetworkConfiguration implements Serializable {

	// The following todo's concern this class as well as all other accessory classes of this package:
	// * todo: implement stricter parameters validation for constructors and all setters
	// * todo: javadocs
	// * todo: override toString()
	// * todo: introduce listeners

	public Node createNode() {
		checkBeforeModifications();
		return new Node(this);
	}

	public Link createLink(Node source, Node destination) {
		checkBeforeModifications();
		return new Link(this, source, destination);
	}

	public MessageFlow createMessageFlow() {
		checkBeforeModifications();
		return new MessageFlow(this);
	}

	public Set<Node> getNodes() {
		return nodesView;
	}

	public Set<Link> getLinks() {
		return linksView;
	}

	public Set<MessageFlow> getFlows() {
		return flowsView;
	}

	public QueueingConfiguration getQueueingConfiguration() {
		return queueingConfiguration;
	}

	public void confirm() throws IllegalStateException { // todo: reconsider the name
		for (Node node : nodes) {
			node.validate();
		}
		for (Link link : links) {
			link.validate();
		}
		for (MessageFlow flow : flows) {
			flow.validate();
		}
		isConfirmed = true;
	}

	public boolean isConfirmed() {
		return isConfirmed;
	}

	// ==================== Implementation ====================

	private transient boolean isConfirmed;

	final Set<Node> nodes = new HashSet<Node>();
	private final Set<Node> nodesView = Collections.unmodifiableSet(nodes);

	final Set<Link> links = new HashSet<Link>();
	private final Set<Link> linksView = Collections.unmodifiableSet(links);

	final Set<MessageFlow> flows = new HashSet<MessageFlow>();
	private final Set<MessageFlow> flowsView = Collections.unmodifiableSet(flows);

	private final QueueingConfiguration queueingConfiguration = new QueueingConfiguration(this);

	void checkBeforeModifications() {
		if (isConfirmed) {
			throw new IllegalStateException("The network configuration may not be modified");
		}
	}

}
